package com.dlc.garbagerecyclebox;

import android.text.TextUtils;

import com.dlc.commonbiz.base.serialport.utils.ByteUtil;
import com.dlc.commonbiz.base.serialport.utils.CheckUtil;
import com.dlc.commonbiz.base.util.SharedPreferencesUtil;
import com.dlc.garbagerecyclebox.bean.CmdGarbageRecyclerCmdBean;
import com.dlc.garbagerecyclebox.log.GarbageRecycleBoxLogFactory;

/**
 * @author :      fangbingran
 * @aescription : 组装命令
 * @date :        2019/07/26  14:17
 */
public class GarbageRecyclerBoxCmdFactory {
    private static byte[] allCmd(byte[] cmd, String strCmdNumber, int dataLength, int destinationAddress, byte versionByte, String data) {
        //       最短字节不包含数据域（帧头(2字节)+协议版本号(1字节)+ 设备地址(1字节)+命令码(2个字节)+ 命令流水号(4个字节)+ 内容长度(1个字节)+内容(N个字节)+校验异或（1个字节））
        byte[] frameHeaderByte = {GarbageRecyclerBoxProtocol.FRAME_HEADER, GarbageRecyclerBoxProtocol.FRAME_HEADER2};

        String frameHeader = ByteUtil.bytes2HexStr(frameHeaderByte);
        //目标地址(1字节)
        String strDestinationAddress = ByteUtil.integer2HexStr(destinationAddress);
        //数据长度
        String strDataLength = ByteUtil.integer2HexStr(dataLength);

        //命令码
        String command = ByteUtil.bytes2HexStr(cmd);
        String version = ByteUtil.bytes2HexStr(new byte[]{versionByte});
        //为本帧数据包括帧头，协议版本号，设备地址，命令码，命令流水号，内容长度，内容在内的全部数据做异或校验。
        String strHeaderToData = frameHeader + version + strDestinationAddress + command + strCmdNumber + strDataLength + data;
        //        String cRc = CheckUtil.getXOR(ByteUtil.hexStr2bytes(strHeaderToData));
        String cRc = CheckUtil.getXOR(strHeaderToData);
        CmdGarbageRecyclerCmdBean.Builder builder = CmdGarbageRecyclerCmdBean.newBuilder()
                .setFrameHeader(frameHeader)
                .setProtocolVersion(version)
                .setDestinationAddress(strDestinationAddress)
                .setCommand(command)
                .setCommandNumber(strCmdNumber)
                .setDataLength(strDataLength)
                .setData(data)
                .setCRC(cRc);
        GarbageRecycleBoxLogFactory.info("发送:" + builder.toString());
        return builder.build();
    }

    public static byte[] allCmd(byte[] cmd, int destinationAddress, String data) {
        int dataLength = TextUtils.isEmpty(data) ? 0 : data.length() / 2;
        //命令码流水号
        String strCmdNumber = ByteUtil.integer2HexStr(addNumber(destinationAddress), 8);
        return allCmd(cmd, strCmdNumber, dataLength, destinationAddress, GarbageRecyclerBoxProtocol.PROTOCOL_VERSION_NUMBER, data);
    }

    public static byte[] allCmd(byte[] cmd, int number, int destinationAddress, String data) {
        int dataLength = TextUtils.isEmpty(data) ? 0 : data.length() / 2;
        //命令码流水号
        String strCmdNumber = ByteUtil.integer2HexStr(number, 8);
        return allCmd(cmd, strCmdNumber, dataLength, destinationAddress, GarbageRecyclerBoxProtocol.PROTOCOL_VERSION_NUMBER, data);
    }

    public static byte[] allCmd(byte[] cmd, String strCmdNumber, int destinationAddress, String data) {
        int dataLength = TextUtils.isEmpty(data) ? 0 : data.length() / 2;
        return allCmd(cmd, strCmdNumber, dataLength, destinationAddress, GarbageRecyclerBoxProtocol.PROTOCOL_VERSION_NUMBER, data);
    }

    private final static String NUMBER = "Garbage_Recycle_Box_Number";

    public static int addNumber(int address) {
        int number = SharedPreferencesUtil.getDefault().getInt(NUMBER + "_" + address, -1);
        if (number <= 0 || number >= GarbageRecyclerBoxProtocol.MAX_CMD_PIPELINE_NUMBER) {
            number = 1;
        } else {
            number++;
        }
        SharedPreferencesUtil.getDefault().saveInt(NUMBER + "_" + address, number);
        return number;
    }

    public static int getNumber(int address) {
        return SharedPreferencesUtil.getDefault().getInt(NUMBER + "_" + address, -1);
    }

    /**
     * 查询命令
     *
     * @param destinationAddress
     * @return
     */
    public static byte[] queryCommand(int destinationAddress) {
        return allCmd(new byte[]{GarbageRecyclerBoxProtocol.CMD_QUERY, GarbageRecyclerBoxProtocol.CMD_ZERO}, "00000000", destinationAddress, "");
    }

    /**
     * 投递命令
     *
     * @param destinationAddress
     * @param deliveryType
     * @return
     */
    public static byte[] deliveryCommand(int destinationAddress, int number, @SwitchType int deliveryType) {
        String data = ByteUtil.integer2HexStr(deliveryType);
        return allCmd(new byte[]{GarbageRecyclerBoxProtocol.CMD_DELIVERY, GarbageRecyclerBoxProtocol.CMD_ZERO}, number, destinationAddress, data);
    }

    /**
     * 回收命令
     *
     * @param destinationAddress
     * @return
     */
    public static byte[] recyclingCommand(int destinationAddress, int number) {
        return allCmd(new byte[]{GarbageRecyclerBoxProtocol.CMD_RECYCLING, GarbageRecyclerBoxProtocol.CMD_ZERO}, number, destinationAddress, "");
    }

    /**
     * 开关上舱门命令数据
     *
     * @return
     */
    public static String getSwitchUpperHatchDoorCommandData(@SwitchType int switchType) {
        return ByteUtil.integer2HexStr(switchType);
    }

    /**
     * IO口控制命令数据
     *
     * @return
     */
    public static String ioPortControlCommand(@IOType int iOType, @SwitchType int switchType) {
        StringBuilder data = new StringBuilder();
        data.append(ByteUtil.integer2HexStr(iOType)).append(ByteUtil.integer2HexStr(switchType));
        return data.toString();
    }

    /**
     * 传送带命令数据
     *
     * @return
     */
    public static String conveyorBeltCommand(@ControlConveyorBeltType int controlConveyorBeltType) {
        return ByteUtil.integer2HexStr(controlConveyorBeltType);
    }

    /**
     * 视觉模块拍照识别命令数据
     *
     * @return
     */
    public static String photoRecognitionToVisionCommand(@PhotoRecognitionType int photoRecognitionType) {
        return ByteUtil.integer2HexStr(photoRecognitionType);
    }

    /**
     * 管理维护命令
     *
     * @param destinationAddress
     * @return
     */
    public static byte[] getManageMaintain(int destinationAddress, byte cmd, int number, String data) {
        return allCmd(new byte[]{GarbageRecyclerBoxProtocol.CMD_MANAGE_MAINTAIN, cmd}, number, destinationAddress, data);
    }

}
